home *** CD-ROM | disk | FTP | other *** search
/ BMUG PD-ROM 1995 Fall / PD-ROM F95.toast / Programming / Programming Languages / UCB Logo 3.0 ƒ / sources / standard source / math.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-14  |  14.3 KB  |  726 lines  |  [TEXT/ttxt]

  1. /*
  2.  *      math.c          logo math functions module              dvb
  3.  *
  4.  *    Copyright (C) 1993 by the Regents of the University of California
  5.  *
  6.  *      This program is free software; you can redistribute it and/or modify
  7.  *      it under the terms of the GNU General Public License as published by
  8.  *      the Free Software Foundation; either version 2 of the License, or
  9.  *      (at your option) any later version.
  10.  *  
  11.  *      This program is distributed in the hope that it will be useful,
  12.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *      GNU General Public License for more details.
  15.  *  
  16.  *      You should have received a copy of the GNU General Public License
  17.  *      along with this program; if not, write to the Free Software
  18.  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  */
  21.  
  22. #include "logo.h"
  23. #include "globals.h"
  24. #include <signal.h>
  25. #include <setjmp.h>
  26. #include <math.h>
  27.  
  28. #define isdigit(dig)    (dig >= '0' && dig <= '9')
  29.  
  30. int numberp(NODE *snd)
  31. {
  32.     int dl,dr, pcnt, plen;
  33.     char *p;
  34.  
  35.     if (is_number(snd)) return(1);
  36.  
  37.     snd = cnv_node_to_strnode(snd);
  38.     if (snd == UNBOUND) return(0);
  39.  
  40.     p = getstrptr(snd); plen = getstrlen(snd); pcnt = dl = dr = 0;
  41.     if (plen >= MAX_NUMBER) {
  42.     return(0);
  43.     }
  44.  
  45.     if (pcnt < plen && *p == '-')
  46.     p++, pcnt++;
  47.  
  48.     while (pcnt < plen && isdigit(*p))
  49.     p++, pcnt++, dl++;
  50.  
  51.     if (pcnt < plen && *p == '.') {
  52.     p++, pcnt++;
  53.     while (pcnt < plen && isdigit(*p))
  54.         p++, pcnt++, dr++;
  55.     }
  56.  
  57.     if (pcnt < plen && (dl || dr) && (*p == 'E' || *p == 'e')) {
  58.     p++, pcnt++;
  59.  
  60.     if (pcnt < plen && *p == '+' || *p == '-')
  61.         p++, pcnt++;
  62.  
  63.     while (pcnt < plen && isdigit(*p))
  64.         p++, pcnt++, dr++;
  65.     }
  66.  
  67.     if ((dl == 0 && dr == 0) || pcnt != plen)
  68.     return (0);
  69.     else
  70.     return (dr + 1);
  71. }
  72.  
  73. NODE *lrandom(NODE *arg)
  74. {
  75.     NODE *val;
  76.     long r;
  77.  
  78.     val = pos_int_arg(arg);
  79.     if (NOT_THROWING) {
  80. #ifdef bsd
  81.         r = (getint(val) == 0 ? 0 : random() % getint(val));
  82. #else
  83.         r = (getint(val) == 0 ? 0 : rand() % getint(val));
  84. #endif
  85.         val = newnode(INT);
  86.         setint(val, (FIXNUM)r);
  87.         return(val);
  88.     } else return(UNBOUND);
  89. }
  90.  
  91. NODE *lrerandom(NODE *arg)
  92. {
  93.     int seed=1;
  94.  
  95.     if (arg != NIL) {
  96.         seed = int_arg(arg);
  97.     }
  98.     if (NOT_THROWING) {
  99. #ifdef bsd
  100.         srandom((int)seed);
  101. #else
  102.         srand((int)seed);
  103. #endif
  104.     }
  105.     return(UNBOUND);
  106. }
  107.  
  108. jmp_buf oflo_buf;
  109.  
  110. #ifdef __ZTC__
  111. #define sig_arg 0
  112. void handle_oflo(int sig) {
  113. #else
  114. #define sig_arg 
  115. void handle_oflo() {
  116. #endif
  117.     longjmp(oflo_buf,1);
  118. }
  119.  
  120. #ifdef vax
  121. void allow_intov() {
  122.     long dummy;
  123.     register long *p = &dummy;
  124.  
  125.     p[2] |= 040;    /* Turn on IV enable in saved PSW (I hate the vax) */
  126. }
  127.  
  128. double infnan() {
  129.     longjmp(oflo_buf,1);
  130. }
  131. #endif
  132.  
  133. #ifdef sun
  134. int matherr(struct exception *x)
  135. {
  136.     if (x->type == UNDERFLOW) return(1);
  137.     longjmp(oflo_buf,1);
  138. }
  139. #endif
  140.  
  141. #ifdef mac
  142. FLONUM degrad = 0.017453292520;
  143. #else
  144. FLONUM degrad = 3.141592653589793227020265931059839203954/180.0;
  145. #endif
  146.  
  147. NODE *binary(NODE *args, char fcn)
  148. {
  149.     NODE *arg, *val;
  150.     BOOLEAN imode;
  151.     FIXNUM iarg, ival, oval, nval;
  152.     FLONUM farg, fval;
  153.     int sign, wantint=0;
  154.  
  155.     arg = numeric_arg(args);
  156.     args = cdr(args);
  157.     if (stopping_flag == THROWING) return UNBOUND;
  158.     if (nodetype(arg) == INT) {
  159.     imode = TRUE;
  160.     ival = getint(arg);
  161.     } else {
  162.     imode = FALSE;
  163.     fval = getfloat(arg);
  164.     }
  165.     if (args == NIL) {    /* one argument supplied */
  166.       if (imode)
  167.     switch(fcn) {
  168.       case '-': ival = -ival; break;
  169.       case '~': ival = ~ival; break;
  170.       case 's':
  171.       case 'c':
  172.       case 't':
  173.       case 'S':
  174.       case 'C':
  175.       case 'T':
  176.       case 'q':
  177.       case 'e':
  178.       case 'g':
  179.       case 'n':
  180.       case '/':
  181.         imode = FALSE;
  182.         fval = (FLONUM)ival;
  183.         break;
  184.     }
  185.       if (imode == FALSE) {
  186.        if (!setjmp(oflo_buf)) {
  187.     switch(fcn) {
  188.       case '-': fval = -fval; break;
  189.       case '/':
  190.         if (fval == 0.0)
  191.         err_logo(BAD_DATA_UNREC,arg);
  192.         else
  193.         fval = 1/fval;
  194.         break;
  195.       case '~': err_logo(BAD_DATA_UNREC,arg); break;
  196.       case 'c':
  197.         fval = 90.0 - fval;
  198.       case 's':
  199.         /* Kahan sez we can't just multiply any old
  200.          * angle by degrad, but have to get into the
  201.          * range 0-45 first */
  202.         sign = (fval < 0.0);
  203.         if (sign) fval = -fval;
  204. #ifndef unix
  205.         fval = fmod(fval,360.0);
  206. #else
  207.         fval = drem(fval,360.0);
  208. #endif
  209.         if (fval > 180.0) {
  210.         fval -= 180.0;
  211.         sign = !sign;
  212.         }
  213.         if (fval > 90.0) fval = 180.0 - fval;
  214.         if (fval > 45.0)
  215.         fval = cos((90.0-fval)*degrad);
  216.         else
  217.         fval = sin(fval*degrad);
  218.         if (sign) fval = -fval;
  219.         break;
  220.       case 't': fval = atan(fval)/degrad; break;
  221.       case 'S': fval = sin(fval); break;
  222.       case 'C': fval = cos(fval); break;
  223.       case 'T': fval = atan(fval); break;
  224.       case 'q': fval = sqrt(fval); break;
  225.       case 'e': fval = exp(fval); break;
  226.       case 'g': fval = log10(fval); break;
  227.       case 'n': fval = log(fval); break;
  228.       case 'r':
  229.         fval += (fval < 0 ? -0.5 : 0.5);
  230.       case 'i':
  231. #ifdef vax
  232.         allow_intov();
  233. #else
  234.         if (fval > (FLONUM)MAXINT ||
  235.             fval < -(FLONUM)MAXINT)
  236.         handle_oflo(sig_arg);
  237. #endif
  238.         signal(SIGFPE, handle_oflo);
  239.         ival = (FIXNUM)fval;
  240.         imode = TRUE;
  241.         signal(SIGFPE, SIG_DFL);
  242.         break;
  243.     }
  244.        } else {    /* overflow */
  245.         if (fcn == 'r' || fcn == 'i') {
  246.           if (fval < 0.0)
  247.         fval = ceil(fval);
  248.           else
  249.         fval = floor(fval);
  250.         } else
  251.         err_logo(BAD_DATA_UNREC,arg);
  252.        }
  253.       }        /* end float case */
  254.     }        /* end monadic */
  255.     while (args != NIL && NOT_THROWING) {
  256.     arg = numeric_arg(args);
  257.     args = cdr(args);
  258.     if (stopping_flag == THROWING) return UNBOUND;
  259.  
  260.     if (nodetype(arg) == INT) {
  261.         if (imode) iarg = getint(arg);
  262.         else farg = (FLONUM)getint(arg);
  263.     } else {
  264.         if (imode) {
  265.         fval = (FLONUM)ival;
  266.         imode = FALSE;
  267.         }
  268.         farg = getfloat(arg);
  269.     }
  270.  
  271.     if (imode) {
  272.         oval = ival;
  273. #ifdef vax
  274.         allow_intov();
  275. #endif
  276.         signal(SIGFPE, handle_oflo);
  277.         if (setjmp(oflo_buf) == 0) {
  278.          switch(fcn) {
  279. #ifdef vax
  280.           case '+': ival += iarg; break;
  281.           case '-': ival -= iarg; break;
  282.           case '*': ival *= iarg; break;
  283. #else
  284.           case '-': iarg = -iarg;
  285.           case '+':
  286.         if (iarg < 0) {
  287.             nval = ival + iarg;
  288.             if (nval >= ival)
  289.             handle_oflo(sig_arg);
  290.             else ival = nval;
  291.         } else {
  292.             nval = ival + iarg;
  293.             if (nval < ival)
  294.             handle_oflo(sig_arg);
  295.             else ival = nval;
  296.         }
  297.         break;
  298. #endif
  299.           case '/':
  300.         if (iarg == 0)
  301.           err_logo(BAD_DATA_UNREC,arg);
  302.         else
  303.           if (ival % iarg != 0) {
  304.             imode = FALSE;
  305.             fval = (FLONUM)ival;
  306.             farg = (FLONUM)iarg;
  307.           }
  308.           else ival /= iarg;
  309.           break;
  310.           case '%':
  311.         ival %= iarg;
  312.         if ((ival < 0) != (iarg < 0))
  313.             ival += iarg;
  314.         break;
  315.           case '&': ival &= iarg; break;
  316.           case '|': ival |= iarg; break;
  317.           case '^': ival ^= iarg; break;
  318.           case 'a':
  319.           case 'l':
  320.         if (iarg < 0) {
  321.           if (fcn == 'a')
  322.             ival >>= -iarg;
  323.           else
  324.             ival = (unsigned)ival
  325.             >> -iarg;
  326.         } else
  327.           ival <<= iarg;
  328.         break;
  329. #ifndef vax
  330.           case '*':
  331.         if (ival < SAFEINT && ival > -SAFEINT &&
  332.             iarg < SAFEINT && iarg > -SAFEINT) {
  333.             ival *= iarg;
  334.             break;
  335.         }
  336.         wantint++;
  337. #endif
  338.           default: /* math library */
  339.         imode = FALSE;
  340.         fval = (FLONUM)ival;
  341.         farg = (FLONUM)iarg;
  342.          }
  343.         } else {    /* integer overflow detected */
  344.         imode = FALSE;
  345.         fval = (FLONUM)oval;
  346.         farg = (FLONUM)iarg;
  347.         }
  348.         signal(SIGFPE,SIG_DFL);
  349.     }
  350.     if (imode == FALSE) {
  351.       signal(SIGFPE,handle_oflo);
  352.       if (setjmp(oflo_buf) == 0) {
  353.         switch(fcn) {
  354.           case '+': fval += farg; break;
  355.           case '-': fval -= farg; break;
  356.           case '*':
  357.         fval *= farg;
  358. #ifndef vax
  359.         if (wantint) {
  360.             wantint = 0;
  361.             if (fval <= MAXINT && fval >= -MAXINT) {
  362.             imode = TRUE;
  363.             ival = fval;
  364.             }
  365.         }
  366. #endif
  367.         break;
  368.           case '/': if (farg == 0.0)
  369.               err_logo(BAD_DATA_UNREC,arg);
  370.             else
  371.               fval /= farg;
  372.             break;
  373.           case 't':
  374.         fval = atan2(farg,fval)/degrad;
  375.         break;
  376.           case 'T':
  377.         fval = atan2(farg,fval);
  378.         break;
  379.           case 'p':
  380.         fval = pow(fval,farg);
  381.         break;
  382.           default: /* logical op */
  383.         if (nodetype(arg) == INT)
  384.           err_logo(BAD_DATA_UNREC, make_floatnode(fval));
  385.         else
  386.           err_logo(BAD_DATA_UNREC,arg);
  387.         }
  388.       } else {    /* floating overflow detected */
  389.         err_logo(BAD_DATA_UNREC,arg);
  390.       }
  391.       signal(SIGFPE,SIG_DFL);
  392.     }    /* end floating point */
  393.     }    /* end dyadic */
  394.     if (NOT_THROWING) {
  395.     if (imode) {
  396.         val = newnode(INT);
  397.         setint(val, ival);
  398.     } else {
  399.         val = newnode(FLOAT);
  400.         setfloat(val, fval);
  401.     }
  402.     return(val);
  403.     }
  404.     return(UNBOUND);
  405. }
  406.  
  407. NODE *ladd(NODE *args)
  408. {
  409.     if (args == NIL) return make_intnode(0);
  410.     return(binary(args, '+'));
  411. }
  412.  
  413. NODE *lsub(NODE *args)
  414. {
  415.     return(binary(args, '-'));
  416. }
  417.  
  418. NODE *lmul(NODE *args)
  419. {
  420.     if (args == NIL) return make_intnode(1);
  421.     return(binary(args, '*'));
  422. }
  423.  
  424. NODE *ldivide(NODE *args)
  425. {
  426.     return(binary(args, '/'));
  427. }
  428.  
  429. NODE *lremainder(NODE *args)
  430. {
  431.     return(binary(args, '%'));
  432. }
  433.  
  434. NODE *lbitand(NODE *args)
  435. {
  436.     if (args == NIL) return make_intnode(-1);
  437.     return(binary(args, '&'));
  438. }
  439.  
  440. NODE *lbitor(NODE *args)
  441. {
  442.     if (args == NIL) return make_intnode(0);
  443.     return(binary(args, '|'));
  444. }
  445.  
  446. NODE *lbitxor(NODE *args)
  447. {
  448.     if (args == NIL) return make_intnode(0);
  449.     return(binary(args, '^'));
  450. }
  451.  
  452. NODE *lashift(NODE *args)
  453. {
  454.     return(binary(args, 'a'));
  455. }
  456.  
  457. NODE *llshift(NODE *args)
  458. {
  459.     return(binary(args, 'l'));
  460. }
  461.  
  462. NODE *lbitnot(NODE *args)
  463. {
  464.     return(binary(args, '~'));
  465. }
  466.  
  467. NODE *lsin(NODE *args)
  468. {
  469.     return(binary(args, 's'));
  470. }
  471.  
  472. NODE *lcos(NODE *args)
  473. {
  474.     return(binary(args, 'c'));
  475. }
  476.  
  477. NODE *latan(NODE *args)
  478. {
  479.     return(binary(args, 't'));
  480. }
  481.  
  482. NODE *lradsin(NODE *args)
  483. {
  484.     return(binary(args, 'S'));
  485. }
  486.  
  487. NODE *lradcos(NODE *args)
  488. {
  489.     return(binary(args, 'C'));
  490. }
  491.  
  492. NODE *lradatan(NODE *args)
  493. {
  494.     return(binary(args, 'T'));
  495. }
  496.  
  497. NODE *lsqrt(NODE *args)
  498. {
  499.     return(binary(args, 'q'));
  500. }
  501.  
  502. NODE *linteg(NODE *args)
  503. {
  504.     return(binary(args, 'i'));
  505. }
  506.  
  507. NODE *lround(NODE *args)
  508. {
  509.     return(binary(args, 'r'));
  510. }
  511.  
  512. NODE *lexp(NODE *args)
  513. {
  514.     return(binary(args, 'e'));
  515. }
  516.  
  517. NODE *llog10(NODE *args)
  518. {
  519.     return(binary(args, 'g'));
  520. }
  521.  
  522. NODE *lln(NODE *args)
  523. {
  524.     return(binary(args, 'n'));
  525. }
  526.  
  527. NODE *lpower(NODE *args)
  528. {
  529.     return(binary(args, 'p'));
  530. }
  531.  
  532. int compare_numnodes(NODE *n1, NODE *n2)
  533. {
  534.     FLONUM f;
  535.     FIXNUM i;
  536.  
  537.     if (nodetype(n1) == INT) {
  538.     if (nodetype(n2) == INT) {
  539.         i = getint(n1) - getint(n2);
  540.         return (i == 0L ? 0 : (i > 0L ? 1 : -1));
  541.     } else {
  542.         f = (FLONUM)getint(n1) - getfloat(n2);
  543.         return(f == 0.0 ? 0 : (f > 0.0 ? 1 : -1));
  544.     }
  545.     }
  546.     else {
  547.     if (nodetype(n2) == INT) {
  548.         f = getfloat(n1) - (FLONUM)getint(n2);
  549.         return(f == 0.0 ? 0 : (f > 0.0 ? 1 : -1));
  550.     }
  551.     else {
  552.         f = getfloat(n1) - getfloat(n2);
  553.         return(f == 0.0 ? 0 : (f > 0.0 ? 1 : -1));
  554.     }
  555.     }
  556. }
  557.  
  558. NODE *torf(BOOLEAN tf) {
  559.     return (tf ? True : False);
  560. }
  561.  
  562. NODE *llessp(NODE *args)
  563. {
  564.     NODE *n1, *n2;
  565.  
  566.     n1 = numeric_arg(args);
  567.     n2 = numeric_arg(cdr(args));
  568.  
  569.     if (NOT_THROWING) {
  570.     return torf(compare_numnodes(n1, n2) < 0);
  571.     }
  572.     return(UNBOUND);
  573. }
  574.  
  575. NODE *lgreaterp(NODE *args)
  576. {
  577.     NODE *n1, *n2;
  578.  
  579.     n1 = numeric_arg(args);
  580.     n2 = numeric_arg(cdr(args));
  581.  
  582.     if (NOT_THROWING) {
  583.     return torf(compare_numnodes(n1, n2) > 0);
  584.     }
  585.     return(UNBOUND);
  586. }
  587.  
  588. int compare_node(NODE *n1, NODE *n2, BOOLEAN ignorecase)
  589. {
  590.     NODE *a1 = NIL, *a2 = NIL, *nn1 = NIL, *nn2 = NIL;
  591.     int icmp, cmp_len;
  592.     NODETYPES nt1, nt2;
  593.  
  594.     if (n1 == n2) return 0;
  595.  
  596.     nt1 = nodetype(n1);
  597.     nt2 = nodetype(n2);
  598.  
  599.     if (!(nt1 & NT_WORD) || !(nt2 & NT_WORD)) return -9999;
  600.  
  601.     if (nt1 == CASEOBJ && nt2 == CASEOBJ && ignorecase &&
  602.      (object__caseobj(n1) == object__caseobj(n2))) return 0;
  603.  
  604.     if ((nt1 & NT_NUMBER) && (nt2 & NT_NUMBER))
  605.     return compare_numnodes(n1, n2);
  606.  
  607.     if (nt1 & NT_NUMBER) {
  608.     nn2 = cnv_node_to_numnode(n2);
  609.     if (nn2 != UNBOUND) {
  610.         icmp = compare_numnodes(n1, nn2);
  611.         gcref(nn2);
  612.         return icmp;
  613.     }
  614.     }
  615.  
  616.     if (nt2 & NT_NUMBER) {
  617.     nn1 = cnv_node_to_numnode(n1);
  618.     if (nn1 != UNBOUND) {
  619.         icmp = compare_numnodes(nn1, n2);
  620.         gcref(nn1);
  621.         return icmp;
  622.     }
  623.     }
  624.  
  625.     a1 = cnv_node_to_strnode(n1);
  626.     a2 = cnv_node_to_strnode(n2);
  627.     nt1 = nodetype(a1);
  628.     nt2 = nodetype(a2);
  629.     if (nt1 == STRING && nt2 == STRING) {
  630.     if ((getstrlen(a1) == getstrlen(a2)) &&
  631.             (getstrptr(a1) == getstrptr(a2)))
  632.         icmp = 0;
  633.     else {
  634.     cmp_len = (getstrlen(a1) > getstrlen(a2)) ?
  635.         getstrlen(a2) : getstrlen(a1);
  636.  
  637.     if (ignorecase)
  638.         icmp = low_strncmp(getstrptr(a1), getstrptr(a2), cmp_len);
  639.     else
  640.         icmp = strncmp(getstrptr(a1), getstrptr(a2), cmp_len);
  641.     if ((getstrlen(a1) != getstrlen(a2)) && icmp == 0)
  642.         icmp = getstrlen(a1) - getstrlen(a2);
  643.     }
  644.     }
  645.     else if (nt1 & NT_BACKSL || nt2 & NT_BACKSL) {
  646.     if ((getstrlen(a1) == getstrlen(a2)) &&
  647.             (getstrptr(a1) == getstrptr(a2)))
  648.         icmp = 0;
  649.     else {
  650.     cmp_len = (getstrlen(a1) > getstrlen(a2)) ?
  651.             getstrlen(a2) : getstrlen(a1);
  652.  
  653.     if (ignorecase)
  654.         icmp = noparitylow_strncmp(getstrptr(a1), getstrptr(a2), cmp_len);
  655.     else
  656.         icmp = noparity_strncmp(getstrptr(a1), getstrptr(a2), cmp_len);
  657.     if ((getstrlen(a1) != getstrlen(a2)) && icmp == 0)
  658.         icmp = getstrlen(a1) - getstrlen(a2);
  659.     }
  660.     }
  661.     else err_logo(FATAL, NIL);
  662.  
  663.     if (a1 != n1) gcref(a1);
  664.     if (a2 != n2) gcref(a2);
  665.     return(icmp);
  666. }
  667.  
  668. BOOLEAN equalp_help(NODE *arg1, NODE *arg2, BOOLEAN ingc)
  669. {
  670.     if (is_list(arg1)) {
  671.     if (!is_list(arg2)) return FALSE;
  672.     while (arg1 != NIL && arg2 != NIL) {
  673.         if (!equalp_help(car(arg1), car(arg2), ingc))
  674.         return FALSE;
  675.         arg1 = cdr(arg1);
  676.         arg2 = cdr(arg2);
  677.         if (check_throwing) break;
  678.     }
  679.     return (arg1 == NIL && arg2 == NIL);
  680.     } else if (is_list(arg2))
  681.     return FALSE;
  682.     else if (nodetype(arg1) == ARRAY) {
  683.     if (nodetype(arg2) != ARRAY) return FALSE;
  684.     return (arg1 == arg2);
  685.     } else if (nodetype(arg2) == ARRAY)
  686.     return FALSE;
  687.     else return (!compare_node(arg1, arg2, ingc));
  688. }
  689.  
  690. NODE *lequalp(NODE *args)
  691. {
  692.     NODE *arg1, *arg2;
  693.     BOOLEAN val;
  694.  
  695.     arg1 = car(args);
  696.     arg2 = cadr(args);
  697.  
  698.     if (compare_node(valnode__caseobj(Caseignoredp), True, TRUE) == 0)
  699.     val = equalp_help(arg1, arg2, TRUE);
  700.     else
  701.     val = equalp_help(arg1, arg2, FALSE);
  702.  
  703.     return(torf(val));
  704. }
  705.  
  706. NODE *l_eq(NODE *args)
  707. {
  708.     return torf(car(args) == cadr(args));
  709. }
  710.  
  711. NODE *lbeforep(NODE *args)
  712. {
  713.     NODE *arg1, *arg2;
  714.     int val;
  715.  
  716.     arg1 = string_arg(args);
  717.     arg2 = string_arg(cdr(args));
  718.  
  719.     if (compare_node(valnode__caseobj(Caseignoredp), True, TRUE) == 0)
  720.     val = compare_node(arg1, arg2, TRUE);
  721.     else
  722.     val = compare_node(arg1, arg2, FALSE);
  723.  
  724.     return (val < 0 ? True : False);
  725. }
  726.